package com.dxl.common.utils;

import java.io.Closeable;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;

/**
 * 通用工具类
 * @author 邓小林
 * 创建时间：2016年4月12日
 */
public final class Utils {
	public static <T extends Object> boolean isNull(T t) {
		return t == null;
	}
	
	public static <T extends Object> boolean isNotNull(T t) {
		return t != null;
	}
	
	public static boolean isBlank(String str) {
		return str == null || str.trim().length() <= 0;
	}
	
	public static boolean isNotBlank(String str) {
		return str != null && str.trim().length() > 0;
	}
	
	
	public static String ignoreFirstTrim(String str, int ignoreCount) {
		if (isNull(str)) {
			return str;
		}
		return ignoreFirst(str.trim(), ignoreCount);
	}
	
	public static Long substract(Long l1, Long l2) {
		if (isNull(l1) && isNotNull(l2)) {
			return -l2;
		} else if (isNull(l1) && isNull(l2)) {
			return 0L;
		} else if (isNotNull(l1) && isNotNull(l2)) {
			return l1 - l2;
		} else {
			return l1;
		}
	}
	
	public static BigDecimal substract(BigDecimal b1, BigDecimal b2) {
		if (isNull(b1) && isNotNull(b2)) {
			return new BigDecimal("0").subtract(b2);
		} else if (isNull(b1) && isNull(b2)) {
			return new BigDecimal("0");
		} else if (isNotNull(b1) && isNotNull(b2)) {
			return b1.subtract(b2);
		} else {
			return b1;
		}
	}
	
	public static String ignoreFirst(String str, int ignoreCount) {
		if (isNull(str)) {
			return str;
		}
		int len = str.length();
		if (ignoreCount >= len) {
			return "";
		}
		if (ignoreCount <= 0) {
			return str;
		}
		return str.substring(ignoreCount);
	}
	
	public static String ignoreLastTrim(String str, int ignoreCount) {
		if (isNull(str)) {
			return str;
		}
		return ignoreLast(str.trim(), ignoreCount);
	}
	
	public static String ignoreLast(String str, int ignoreCount) {
		if (isNull(str)) {
			return str;
		}
		int len = str.length();
		if (ignoreCount >= len) {
			return "";
		}
		if (ignoreCount <= 0) {
			return str;
		}
		return str.substring(0, len - ignoreCount);
	}
	
	
	public static String toSafeString(String str) {
		return str == null ? "" : str;
	}
	
	public static <T extends Object> boolean isEmpty(T[] ts) {
		return ts == null || ts.length <= 0;
	}
	
	public static <T extends Object> boolean isNotEmpty(T[] ts) {
		return ts != null && ts.length > 0;
	}
	
	public static <T extends Object> boolean isEmpty(Collection<T> ts) {
		return ts == null || ts.size() <= 0;
	}
	
	public static <T extends Object> boolean isNotEmpty(Collection<T> ts) {
		return ts != null && ts.size() > 0;
	}
	
	public static <T extends Object> boolean isEmpty(Map<T, T> map) {
		return map == null || map.size() <= 0;
	}
	
	public static <K extends Object, V extends Object> boolean isNotEmpty(Map<K, V> map) {
		return map != null && map.size() > 0;
	}
	
	public static Double toDouble(String dStr) {
		try {
			return Double.parseDouble(dStr);
		} catch (Exception e) {
			// ignore
		}
		return null;
	}
	
	public static Integer toInt(String iStr) {
		try {
			return Integer.parseInt(iStr);
		} catch (Exception e) {
			// ignore
		}
		return null;
	}
	
	public static Long toLong(String lStr) {
		try {
			return Long.parseLong(lStr);
		} catch (Exception e) {
			// ignore
		}
		return null;
	}
	
	public static BigDecimal toBigDecimal(String s) {
		try {
			return new BigDecimal(s);
		} catch (Exception e) {
			// ignore
		}
		return null;
	}
	
	public static Long[] toLongs(String lStr, String separator) {
		if (Utils.isBlank(lStr)) {
			return null;
		}
		String[] ls = StringUtils.split(lStr, separator);
		List<Long> longs = new ArrayList<Long>();
		Long lv;
		for (String l : ls) {
			lv = toLong(l);
			if (isNotNull(lv)) {
				longs.add(lv);
			}
		}
		return longs.toArray(new Long[0]);
	}
	
	public static Integer randomInt(int factor) {
		return (int)(Math.random() * factor);
	}
	
	public static Double randomDouble(int factor) {
		return Math.random() * factor;
	}
	
	public static <T extends Object> T random(T[] ts) {
		if (isEmpty(ts)) {
			return null;
		}
		return ts[Math.abs(UUID.randomUUID().toString().hashCode()) % ts.length];
	}	
	
	public static <T extends Closeable> void closeQuietly(T t) {
		try {
			if (isNotNull(t)) {
				t.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void delayMillseconds(long millseconds) {
		try {
			Thread.sleep(millseconds);
		} catch (Exception e) {
			// ignore
		}
	}
	
	/**
	 * 将类名或者属性名转换为数据库表或者字段名，下划线分隔单词
	 * @param str
	 * @return
	 */
	public static String toDBName(String str) {
		if (Utils.isBlank(str)) {
			return "";
		}
		char[] cs = str.toCharArray();
		int len = cs.length;
		String rst = "";
		for (int i = 0; i < len; i++) {
			if (isNotBlank(rst) && Character.isUpperCase(cs[i])) {
				rst += '_';
			}
			rst += cs[i];
		}
		return "`" + rst.toLowerCase() + "`";
	}
	
	public static long random(long max) {
		return (long) (Math.random() * max);
	}
	
	public static String encode(String str, String encoding) {
		String encode = str;
		try {
			encode = URLEncoder.encode(str, encoding);
		} catch (UnsupportedEncodingException e) {
			// ignore
		}
		return encode;
	}
	
	public static String trim(String str) {
		return str == null ? "" : str.trim();
	}
	
	public static String extractParamValue(String link, String paramKey) {
		if (isBlank(link) || isBlank(paramKey)) {
			return "";
		}
		String[] ps = StringUtils.split(link, "?");
		for (String p : ps) {
			if (Utils.isBlank(p) || !p.contains("=")) {
				continue;
			}
			String[] parts = StringUtils.split(p, "&"), tmp;
			for (String part : parts) {
				if (isNotBlank(part) && part.contains("=")) {
					tmp = StringUtils.split(part, "=");
					if (isNotEmpty(tmp) && tmp.length == 2 && trim(tmp[0]).equals(paramKey)) {
						return tmp[1];
					}
				}
			}
		}
		return "";
	}
	
	public static Integer extractInteger(String s) {
		if (isBlank(s)) {
			return null;
		}
		char[] cs = s.toCharArray();
		String si = "";
		for (char c : cs) {
			if (isNotBlank(si) && !Character.isDigit(c)) {
				break;
			}
			if (Character.isDigit(c)) {
				si += c;
			}
		}
		return toInt(si);
	}
	
	public static Integer[] extractIntegers(String s) {
		if (isBlank(s)) {
			return null;
		}
		char[] cs = s.toCharArray();
		String si = "";
		List<Integer> rst = new ArrayList<Integer>();
		char c;
		int len = cs.length;
		for (int i = 0; i < len; i++) {
			c = cs[i];
			if (Character.isDigit(c)) {
				si += c;
			} else {
				if (isNotBlank(si)) {
					rst.add(toInt(si));
					si = "";
				}
			}
			if (i == len - 1 && isNotBlank(si)) {
				rst.add(toInt(si));
			}
		}
		return rst.toArray(new Integer[0]);
	}
	
	public static Long extractLong(String s) {
		if (isBlank(s)) {
			return null;
		}
		char[] cs = s.toCharArray();
		String si = "";
		for (char c : cs) {
			if (isNotBlank(si) && !Character.isDigit(c)) {
				break;
			}
			if (Character.isDigit(c)) {
				si += c;
			}
		}
		return toLong(si);
	}
	
	public static Double extractDouble(String s) {
		if (isBlank(s)) {
			return null;
		}
		char[] cs = s.toCharArray();
		String sd = "";
		for (char c : cs) {
			if (isNotBlank(sd) && !Character.isDigit(c) && c != '.') {
				break;
			}
			if (isNotBlank(sd) && sd.contains(".") && !Character.isDigit(c)) {
				break;
			}
			if (Character.isDigit(c) || c == '.') {
				sd += c;
			}
		}
		return toDouble(sd);
	}
	
	public static BigDecimal extractBigDecimal(String s) {
		if (isBlank(s)) {
			return null;
		}
		char[] cs = s.toCharArray();
		String sd = "";
		for (char c : cs) {
			if (isNotBlank(sd) && !Character.isDigit(c) && c != '.') {
				break;
			}
			if (isNotBlank(sd) && sd.contains(".") && !Character.isDigit(c)) {
				break;
			}
			if (Character.isDigit(c) || c == '.') {
				sd += c;
			}
		}
		return toBigDecimal(sd);
	}
	
	public static <T extends Object> String join(Collection<T> objs, String separater) {
		if (isEmpty(objs)) {
			return "";
		}
		String rst = "";
		int i = 0;
		for (Object obj : objs) {
			if (i > 0) {
				rst += separater;
			}
			rst += obj;
			i++;
		}
		return rst;
	}
	
	public static <T extends Object> String join(T[] objs, String separater) {
		if (isEmpty(objs)) {
			return "";
		}
		String rst = "";
		int i = 0;
		for (Object obj : objs) {
			if (i > 0) {
				rst += separater;
			}
			rst += obj;
			i++;
		}
		return rst;
	}
	
	/**

	 * 字符数组用connecter连接成字符串

	 */
	public static String join(String[] strs, String connecter, int startIndex) {
		if (isNotEmpty(strs)) {
			StringBuilder sb = new StringBuilder();
			for (int i = startIndex; i < strs.length; i++) {
				if (i > startIndex) {
					sb.append(connecter);
				}
				sb.append(strs[i]);
			}
			return sb.toString();
		}
		return "";
	}
	
	public static String decode(String s, String encoding) {
		if (isBlank(s) || isBlank(encoding)) {
			return s;
		}
		try {
			return URLDecoder.decode(s, encoding);
		} catch (Exception e) {
			return s;
		}
	}
	
	public static String resplitBySpace(String s) {
		if (isBlank(s)) {
			return "";
		}
		String[] parts = StringUtils.split(s, " ");
		String rst = "";
		for (String part : parts) {
			if (isBlank(part)) {
				continue;
			}
			if (isNotBlank(rst)) {
				rst += " ";
			}
			rst += part;
		}
		return rst;
	}
	
	/**
	 * 1月2天3时5分 这样的字符创转成分钟，月按30天算
	 * @param str
	 * @return
	 */
	public static Long strToMins(String str) {
		if (isBlank(str)) {
			return 0L;
		}
		Long mins = 0L, l;
		Long[] minFactor = {1L, 60L, 24L * 60, 30L * 24L * 60L};
		String[] parts = str.trim().split("[\u4e00-\u9fa5]");
		int len = parts.length;
		for (int i = len - 1, j = 0; i >= 0 && j < minFactor.length; i--, j++) {
			l = Utils.toLong(parts[i]);
			if (isNotNull(l)) {
				mins += l * minFactor[j];
			}
		}
		return mins;
	}
	
	public static void main(String args[]) {
		
	}
}
